#include "Texture.h"

#include <IL/il.h>

std::map<std::string, std::shared_ptr<Texture>> Texture::textureMap;

Texture::Texture()
{

}

Texture::Texture(std::string fullFilePath)
{
	SetPath(fullFilePath);
	SetFileName(GetFileName(fullFilePath));
}

Texture::~Texture()
{

}

void Texture::SetTextureID(GLuint id)
{
	this->textureID = id;
}

std::string Texture::GetBasePath(const std::string& path)
{
	size_t pos = path.find_last_of("\\/");
	return (std::string::npos == pos) ? "" : path.substr(0, pos + 1);
}

std::string Texture::GetFileName(const std::string& path)
{
	size_t pos = path.find_last_of("\\/");
	return (std::string::npos == pos) ? "" : path.substr(pos+1);
}

bool Texture::LoadImage()
{
	ILuint imageIds = 0;
	ilGenImages(1, &imageIds); // Generation of numTextures image names 
	ilBindImage(imageIds); // Binding of DevIL image name 
	ILboolean success = ilLoadImage(path.c_str());
	
	if (success) // If no error occured: 
	{
		if(ilGetInteger(IL_IMAGE_FORMAT) == IL_RGB)
		{
			success = ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE);
		}
		else if(ilGetInteger(IL_IMAGE_FORMAT) == IL_RGBA)
		{
			success = ilConvertImage(IL_RGBA, IL_UNSIGNED_BYTE);
		}

		if(!success)
		{
			return false;
		}

		glGenTextures(1, &textureID); // Texture name generation 
		Bind();
		GLenum e = glGetError();
		//redefine standard texture values
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // We will use linear interpolation for magnification filter
		e = glGetError();
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // We will use linear interpolation for minifying filter
		e = glGetError();
		glTexImage2D(GL_TEXTURE_2D, 0, ilGetInteger(IL_IMAGE_BPP), ilGetInteger(IL_IMAGE_WIDTH),
			ilGetInteger(IL_IMAGE_HEIGHT), 0, ilGetInteger(IL_IMAGE_FORMAT), GL_UNSIGNED_BYTE,
			ilGetData()); // Texture specification 
		e = glGetError();
		Unbind();

		//setup the references properly
		SetPath(fileName);
		Texture::textureMap.insert(std::pair<std::string, std::shared_ptr<Texture>>(fileName, this));

		//clean up
		ilBindImage(0);
		ilDeleteImages(1, &imageIds); // Because we have already copied image data into texture data we can release memory used by image. 

		return true;
	}

	return false;
}
